using System;
using System.Collections;
using Sedna.Core.Common;

namespace Sedna.Core.Controller
{
	public interface IExecutionContext : IDictionary
	{

        string CurrentScopePrefix
        {
            get;
            set;
        }
	    
		/// <summary>
		/// returns a CommandArgument that was assigned to a Button (or any other control that supports it)
		/// can be null if no CommandArgument is assigned
		/// </summary>
		string CommandArgument
		{
			get;
		}	

		/// <summary>
		/// returns a command name (used if a command was invoked (e.g. a Button clicked))
		/// </summary>
		string CommandName
		{
			get;
		}

//		/// <summary>
//		/// returns a current control context execution prefix
//		/// </summary>
//		string CurrentExecutionContextPrefix
//		{
//			get;
//			set;
//		}
//
		/// <summary>
		/// returns a reference to a current configuration within an action is invoked
		/// </summary>
		IConfiguration CurrentConfiguration
		{
			get;
		}

		string PostBackSourceControl
		{
			get;
		}

		/// <summary>
		/// returns a name of a curren action that is invoked
		/// </summary>
		string ActionName
		{
			get;
		}


		bool IsPostBack
		{
			get;
		}

        ICallContext CallContext
        {
            get;
        }


        string AlertMessage
        {
            get;
            set;
        }

        string AlertMessageKey
        {
            get;
            set;
        }
	    
		/// <summary>
		/// sets a value for a 'current scope context prefix' + '.' + 'postfix'
		/// </summary>
		/// <param name="postfix">execution context postfix (e.g. for a text box it will be 'text', please note - no separator (i.e. '.'/dot) is necessary)</param>
		/// <param name="value">any value to set into execution context</param>
		void SetToCurrentScope(string postfix, object value);

		/// <summary>
		/// retreives a value from an execution context mapped under the key 'current scope prefix' + '.' + 'postfix'
		/// </summary>
		/// <param name="postfix">execution context postfix, WHIOUT '.'/dot</param>
		/// <returns>a value mappen in the execution context or null if no value is found</returns>
		object GetFromCurrentScope(string postfix);

		/// <summary>
		/// Set <c>null</c> value in the specified scope
		/// </summary>
		void ClearScopedValue(String key, Scope scope);

		/// <summary>
		/// Sets a value in the specified <c>Scope</c>.
		/// If <c>Scope</c> is a <c>Request</c> or <c>IoCContainer</c> when throws exception.
		/// If <c>Scope</c> is a <c>Cookie</c> when <c>value</c> must be <c>HttpCookie</c> instance,
		/// whose property <c>Name</c> is replaced by <c>key</c> parameter, otherwise throws exception
		/// </summary>
		void SetScopedValue(String key, Object value, Scope scope);

		/// <summary>
		/// Retreives a value from specified <c>Scope</c>
		/// </summary>
		object GetScopedValue(String key, Scope scope);


		/// <summary>
		/// sets a specified value into the ExecutionContext taking Scope (which is a mandatory part of a path)
		/// into account. This method can set up simple objects into the ExecutionContext mapped to the 
		/// specified key or it can set up a property of either already existent or newly created complex object.
		/// In the latter case the dot-based notation is used. 
		/// 
		/// E.g. to set up a string object into a context use the following path:
		/// 'Session.myvalue'
		/// 
		/// To set up an object alternative to something simple, like a User domain object use the following path:
		/// 'Session.myUser'
		/// 
		/// To set up a property of a complex object (note, property names are case-insensitive, whereas the rest of the path (apart from scope) is case sensitive):
		/// 'Session.myUser.Username'
		/// or
		/// 'Session.myUser.username'
		/// but NOT
		/// 'Session.MYUSER.Username'
		/// 
		/// If an obje is not in the Context and an object is a simple one (like string or anything else that does not use navigation)
		/// an object is automatically created.
		/// You can specify a type of an object to create in the ExecutionContext:
		/// 'Session.{User}myUser.Username'
		/// 
		/// Note that you can use short names for objects that are 
		/// registered in the <see cref="Sedna.Core.Common.Objects.Navigation.IScopePathParser"/> implementation (by default, it is all domain objects, for instance)
		/// so that the following paths are equivalent:
		/// 'Session.{User}myUser.username'
		/// 'session.{Sedna.Domain.User}.UserNAME'
		/// 'session.{Sedna.Domain.User, Sedna.Domain}.uSeRnAmE'
		/// </summary>
		void SetPropertyValue(string path, object value);

		/// <summary>
		/// the opposite method to the SetPropertyValue. This method uses the same 
		/// path notation including specification of an object Type. 
		/// In case a Type is specified, an object, if it happens to be in the ExecutionContext,
		/// is checked against type compatability.
		/// </summary>
		/// <param name="path"></param>
		/// <returns></returns>
		object GetPropertyValue(string path);
	}
}
